home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Hot Mix 17
/
Hot Mix 17.iso
/
HM17_SGI
/
research
/
lib
/
search3d.pro
< prev
next >
Wrap
Text File
|
1997-07-08
|
8KB
|
193 lines
; $Id: search3d.pro,v 1.7 1997/01/15 03:11:50 ali Exp $
; Copyright (c) 1992-1997, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
;
;+
; NAME:
; SEARCH3D
;
; PURPOSE:
; This function finds "objects" or regions of similar data
; values within a 3-D array of data. Given a starting location
; and a range of values to search for, SEARCH3D will find all
; the cells within the array that are within the specified range
; of values, and have some path of connectivity through these cells
; to the starting location. See the procedure "SEARCH2D" for the
; two dimensional case.
;
; This function returns a list of the array subscripts that define
; the selected object or region.
;
; CATEGORY:
; Data subsetting.
; Image manipulation.
;
; CALLING SEQUENCE:
; Region = SEARCH3D(Array, Xpos, Ypos, Zpos, Min_val, Max_val)
;
; INPUTS:
; Array: The 3-D array of data to search.
; Data type : Any 3-D array except string or structure.
; Xpos: The X coordinate(s) (first subscript into the 3-D Array)
; of the seed point(s) for the search. Xpos can be a
; single value, or an array of subscripts specifying the
; X coordinates of a seed region. Xpos must have the same
; number of elements as Ypos and Zpos.
; Data type : Long or Lonarr.
; Ypos: The Y coordinate(s) (second subscript into the 3-D Array)
; of the seed point(s) for the search. Ypos can be a
; single value, or an array of subscripts specifying the
; Y coordinates of a seed region. Ypos must have the same
; number of elements as Xpos and Zpos.
; Data type : Long or Lonarr.
; Zpos: The Z coordinate(s) (third subscript into the 3-D Array)
; of the seed point(s) for the search. Zpos can be a
; single value, or an array of subscripts specifying the
; Z coordinates of a seed region. Zpos must have the same
; number of elements as Xpos and Ypos.
; Data type : Long or Lonarr.
; Min_val: The minimum data value to search for. All cells that
; are connected to the starting cell, and have a value
; greater than or equal to Min_val and less than or equal
; to Max_val, will be considered part of the "object".
; If omitted, the default is MIN(Array[Xpos, Ypos, Zpos]) .
; Max_val: The maximum data value to search for.
; If omitted, the default is MAX(Array[Xpos, Ypos, Zpos]) .
;
; KEYWORD PARAMETERS:
; IMAGE: If set, SEARCH3D returns a bi-level volume (3-D byte array)
; with the same dimensions as Array, containing the value
; (1) where the object is, and (0) where it isn't.
; DIAGONAL: Normally, cells are considered adjacent only when
; cubes surrounding the cells share a common face.
; If a non-zero value is passed to DIAGONAL then
; SEARCH3D will also locate cells meeting the search
; criteria whose surrounding cubes share a common
; edge or corner. The default is no diagonal searching.
; Data type : int
;
; DECREASE: This keyword is now obsolete as are INCREASE and LPF_BAND.
; A better way to perform this operation is to pre-process
; the Array parameter before passing to SEARCH3D.
; INCREASE: See the DECREASE keyword.
; LPF_BAND: See the DECREASE keyword.
;
; OUTPUTS:
; This function returns a list of the indices into the 3-D array
; that are part of the located object or region. This list is
; returned as a LONARR(n) where n is the number of cells found.
;
; If the returned array of indices is called Region, and the
; size of the 3-D volume of data is size_x by size_y by size_z,
; then the actual X, Y, and Z indices can be obtained by using
; the following algorithm :
;
; index_z = Region / (size_x * size_y)
; index_y = (Region - (index_z * size_x * size_y)) / size_x
; index_x = (Region - (index_z * size_x * size_y)) - (index_y * size_x)
;
; The object within the 3-D Array could then be subscripted as :
;
; Array[Region]
; OR
; Array[index_x, index_y, index_z]
;
; If the IMAGE keyword is set, however, SEARCH3D returns a bi-level
; volume (3-D byte array) with the same dimensions as Array, containing
; the value (1) where the object is, and (0) where it isn't.
;
; EXAMPLE:
; Find all the indices corresponding to an object contained in a
; 3-D volume of data.
;
; ; Create some data.
; vol = RANDOMU(s, 40, 40, 40)
; vol[3:13, 1:15, 17:33] = 1.3
; vol[15:25, 5:25, 15:25] = 0.2
; vol[5:30,17:38,7:28] = 1.3
; vol[9:23, 16:27, 7:33] = 1.5
;
; ; Search for an object starting at (6, 22, 16) whose data values
; ; are between (1.2) and (1.4)..
; Region = SEARCH3D(vol, 6, 22, 16, 1.2, 1.4, /DIAGONAL)
;
; ; Scale the background cells into the range 0 to 127.
; vol = BYTSCL(vol, TOP=127B)
;
; ; Highlight the object region by setting it to 255.
; vol[Region] = 255B
;
; ; Set up a 3-D view.
; Window, 0, Xsize=640, Ysize=512, Retain=2
; Create_View, Xmax=39, Ymax=39, Zmax=39, ax=(-30), az=30, zoom=0.8
;
; ; Display the volume with the highlighted object in it.
; TVSCL, PROJECT_VOL(vol, 64, 64, 40, Depth_Q=0.4)
;
; MODIFICATION HISTORY:
; Written by: Daniel Carr. Thu Sep 3 17:36:04 MDT 1992
; Modified: Daniel Carr.
; Re-wrote to improve performance using "DILATE".
; Obsoleted keywords INCREASE, DECREASE, and LPF_BAND.
; Added IMAGE keyword.
;-
FUNCTION Search3d, array, xpos, ypos, zpos, min_val, max_val, $
Diagonal=diagonal, Object=object, Decrease=decrease, $
Increase=increase, Lpf_band=smooth_band
ON_ERROR, 2
IF (N_Elements(decrease) GT 0L) THEN $
Print, 'Search3D: Obsolete keyword "DECREASE" ignored.'
IF (N_Elements(increase) GT 0L) THEN $
Print, 'Search3D: Obsolete keyword "INCREASE" ignored.'
IF (N_Elements(smooth_band) GT 0L) THEN $
Print, 'Search3D: Obsolete keyword "LPF_BAND" ignored.'
IF (N_Elements(min_val) LE 0L) THEN min_val = MIN(array[xpos, ypos, zpos], Max=max_val)
IF (N_Elements(max_val) LE 0L) THEN max_val = MAX(array[xpos, ypos, zpos])
s = Bytarr(3, 3, 3)
IF (Keyword_Set(diagonal)) THEN s[*] = 1B $
ELSE BEGIN
s[1, *, *] = 1B
s[*, 1, *] = 1B
s[*, *, 1] = 1B
ENDELSE
size_array = size(array)
xmax = size_array[1] - 1L
ymax = size_array[2] - 1L
zmax = size_array[3] - 1L
vol = Bytarr(size_array[1], size_array[2], size_array[3])
vol[xpos, ypos, zpos] = 1B
; Since "DILATE" does not handle the edges, it is necessary
; to propagate the edges manually.
vol[1L, *, *] = vol[1L, *, *] > vol[0L, *, *]
vol[xmax-1L, *, *] = vol[xmax-1L, *, *] > vol[xmax, *, *]
vol[*, 1L, *] = vol[*, 1L, *] > vol[*, 0L, *]
vol[*, ymax-1L, *] = vol[*, ymax-1L, *] > vol[*, ymax, *]
vol[0, 0, 1L] = vol[*, *, 1L] > vol[*, *, 0L]
vol[0, 0, zmax-1L] = vol[*, *, zmax-1L] > vol[*, *, zmax]
vol = Temporary(vol) and ((array GE min_val) and (array LE max_val))
vol[xpos, ypos, zpos] = 1B
last_found = 0L
ne_obj = N_Elements(Where(vol))
WHILE (ne_obj ne last_found) DO BEGIN
vol = Dilate(Temporary(vol), s)
vol = Temporary(vol) and ((array GE min_val) and (array LE max_val))
vol[xpos, ypos, zpos] = 1B
last_found = ne_obj
ne_obj = N_Elements(Where(vol))
ENDWHILE
IF (Keyword_Set(object)) THEN RETURN, vol $
ELSE RETURN, Where(vol)
END